; 此程序是写来调试lib.inc的几个函数的。
; 代码有误导致程序运行不出来，用这个程序来单步调试lib里的程序哪里出了错。
%include "pm.inc"

%ifdef DOS_DEBUG
org 0100h
%else
org 07c00h
%endif

%define TEST_DISP_STR


PageDirBase equ 200000h
PageTblBase equ 201000h

jmp LABEL_BEGIN

[SECTION .gdt]
LABEL_GDT: Descriptor 0, 0, 0
LABEL_DESC_CODE_TEST: Descriptor 0, CodeLen - 1, DA_C + DA_32
LABEL_DESC_DATA: Descriptor 0, DataLen - 1, DA_DRW
LABEL_DESC_STACK: Descriptor 0, TopOfStack, DA_DRWA + DA_32
LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW

GdtLen equ $ - LABEL_GDT
GdtPtr dw GdtLen - 1
    dd 0

SelectorCodeTest equ LABEL_DESC_CODE_TEST - LABEL_GDT
SelectorData equ LABEL_DESC_DATA - LABEL_GDT
SelectorStack equ LABEL_DESC_STACK - LABEL_GDT
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT

[SECTION .ss]
LABEL_STACK:
	times 64 db 0
TopOfStack equ $ - LABEL_STACK - 1

[SECTION .data1]
ALIGN 32
[BITS 32]
LABEL_DATA:
%ifdef TEST_DISP_STR
	TestMessage: db "hello", 0Ah, 0Ah, 0
	Off_TestMessage equ TestMessage - LABEL_DATA
	Return: db 0ah, 0
	Off_Return equ Return - LABEL_DATA
%endif
%ifdef TEST_DISP_INT:
	num1: dd 0x12345678
    Off_num1 equ num1 - LABEL_DATA
    num2: db 0x12, 0x34, 0x56, 0x78
    Off_num2 equ num2 - LABEL_DATA
%endif
	DispPos dd 0
	dwDispPos equ DispPos - LABEL_DATA
	
DataLen equ $ - LABEL_DATA
	
	


[SECTION .s16]
[BITS 16]
LABEL_BEGIN:
	mov ax, cs
	mov ds, ax
	mov es, ax
	mov ss, ax
	mov sp, 0100h
	
	mov eax, 0
	mov ax, cs
	shl eax, 4
	add eax, LABEL_CODE32
	mov [LABEL_DESC_CODE_TEST + 2], ax
	shr eax, 16
	mov [LABEL_DESC_CODE_TEST + 4], al
	mov [LABEL_DESC_CODE_TEST + 7], ah

	
	mov eax, 0
	mov ax, ds
	shl eax, 4
	add eax, LABEL_DATA
	mov [LABEL_DESC_DATA + 2], ax
	shr eax, 16
	mov [LABEL_DESC_DATA + 4], al
	mov [LABEL_DESC_DATA + 7], ah

	
	mov eax, 0
	mov ax, ds
	shl eax, 4
	add eax, LABEL_STACK
	mov [LABEL_DESC_STACK + 2], ax
	shr eax, 16
	mov [LABEL_DESC_STACK + 4], al
	mov [LABEL_DESC_STACK + 7], ah

	mov eax, 0
	mov ax, ds
	shl eax, 4
	add eax, LABEL_GDT
	mov dword [GdtPtr + 2], eax

	lgdt [GdtPtr]
	
	cli

	in al, 92h
	or al, 00000010b
	out 92h, al
	
	mov eax, cr0
	or al, 1
	mov cr0, eax

	jmp dword SelectorCodeTest:0
		

; end of section .s16

[SECTION .s32]
[BITS 32]
LABEL_CODE32:
	mov ax, SelectorData
	mov ds, ax

	mov ax, SelectorStack
	mov ss, ax

	mov ax, SelectorVideo
	mov gs, ax

	mov esp, TopOfStack

%ifdef TEST_DISP_STR
	push Off_TestMessage
	call DispStr
	add esp, 4

	push Off_Return
	call DispStr
	add esp, 4

	push Off_TestMessage
    call DispStr
    add esp, 4
%endif
%ifdef TEST_DISP_INT
	
%endif

	jmp $push dword [Off_num1]
    call DispInt
    add esp, 4

    push dword [Off_num2]
    call DispInt
    add esp, 4

%ifdef TEST_DISP_INT
DispAL:
	push ecx
	push edx
	push edi
	
	mov edi, [dwDispPos]
	mov ah, 0Fh
	mov dl, al
	shr al, 4
	mov ecx, 2
.loop:
	and al, 01111b
	cmp al, 9
	ja .1
	add al, '0'
	jmp .2
.1:
	sub al, 10
	add al, 'A'
.2:
	mov [gs:edi], ax
	mov al, dl
	add edi, 2
	loop .loop
	
	
	mov [dwDispPos], edi
	
	pop edi
	pop edx
	pop ecx
	ret
	
DispInt:
	mov eax, [esp + 4]
	shr eax, 24
	call DispAL
	
	mov eax, [esp + 4]
	shr eax, 16
	call DispAL
	
	mov eax, [esp + 4]
	shr eax, 8
	call DispAL
	
	mov eax, [esp + 4]
	call DispAL
	
	push edi
	mov edi, [dwDispPos]
	mov ah, 07H
	mov al, 'h'
	mov [gs:edi], ax
	add edi, 4
	mov [dwDispPos], edi
	
	pop edi
	ret
%endif

%ifdef TEST_DISP_STR	
DispStr:
	push ebp
	mov ebp, esp
	
	push ebx
	push esi
	push edi
	
	mov esi, [ebp + 8]
	mov edi, [dwDispPos]
	mov ah, 0Fh
	
.1:
	; 相当于mov al, [ds:esi], inc esi
	lodsb
	test al, al
	jz .2
	cmp al, 0Ah
	jnz .3
	push eax
	call DispReturn
	pop eax
	mov edi, [dwDispPos]
	jmp .1
.3:
	mov [gs:edi], ax
	add edi, 2
	jmp .1

.2:
	mov dword [dwDispPos], edi
	pop edi
	pop esi
	pop ebx
	
	pop ebp
	ret
	
; 此处跟于渊老师的稍微不一样，显示回车我没有调用DispStr，而是反过来
DispReturn:
	push ebx
	mov eax, [dwDispPos]
	mov bl, 160
	div bl
	and eax, 0FFh
	inc eax
	mov bl, 160
	mul bl
	mov [dwDispPos], eax
	pop ebx
	ret
%endif
CodeLen equ $ - LABEL_CODE32
	

